﻿using System;
using System.Collections.Generic;
using System.Configuration;
using BitCoinSharp;
using log4net;
using Taype.Trading.BTC.MtGoxAPIClient.JSONObjects;
using Taype.Trading.BTC.Utilities;

namespace Taype.Trading.BTC.MtGoxAPIClient
{
    /// <summary>
    /// This class implements v1 of the MtGox API as specified at https://en.bitcoin.it/wiki/MtGox/API#Methods_API_version_1
    /// </summary>
    public class v1
    {
        private readonly ILog logger;

        private string baseURL = "https://mtgox.com/api/";

        private string apiKey = ConfigurationManager.AppSettings["apikey"];

        private string apiSecret = ConfigurationManager.AppSettings["apiSecret"];

        public v1()
        {
            log4net.Config.XmlConfigurator.Configure();
            logger = LogManager.GetLogger(typeof(v1));
        }

        /// <summary>
        /// Multi Currency Ticker
        /// https://mtgox.com/api/1/BTCUSD/public/ticker
        /// https://mtgox.com/api/1/BTCEUR/public/ticker
        /// returns the current ticker for the selected currency:
        /// {
        /// "result":"success",
        /// "return":
        ///  {
        ///  "high": {"value":"5.70653","value_int":"570653","display":"$5.70653","currency":"USD"},
        ///  "low": {"value":"5.4145","value_int":"541450","display":"$5.41450","currency":"USD"},
        ///  "avg": {"value":"5.561119626","value_int":"556112","display":"$5.56112","currency":"USD"},
        ///  "vwap": {"value":"5.610480461","value_int":"561048","display":"$5.61048","currency":"USD"},
        ///  "vol":
        ///  {
        ///   "value":"55829.58960346",
        ///   "value_int":"5582958960346",
        ///   "display":"55,829.58960346\u00a0BTC",
        ///   "currency":"BTC"
        ///  },
        ///  "last_local":{"value":"5.5594","value_int":"555940","display":"$5.55940","currency":"USD"},
        ///  "last_orig":{"value":"5.5594","value_int":"555940","display":"$5.55940","currency":"USD"},
        ///  "last":{"value":"5.5594","value_int":"555940","display":"$5.55940","currency":"USD"},
        ///  "buy":{"value":"5.53587","value_int":"553587","display":"$5.53587","currency":"USD"},
        ///  "sell":{"value":"5.56031","value_int":"556031","display":"$5.56031","currency":"USD"}
        ///  }
        /// note : last_local include only the last trade in the selected currency, last_orig include data of the original last trade ( currency,price in currency . . . ),last can be a conversion of the last trde in another currency  
        /// </summary>
        /// <param name="currency1"></param>
        /// <param name="currency2"></param>
        /// <returns></returns>
        public MtGoxMultiCurrencyTickerItem multiCurrencyTicker(MtGoxCurrencySymbol currency1, MtGoxCurrencySymbol currency2)
        {
            string url = (this.baseURL) + "1/" + currency1.ToString() + currency2.ToString() + "/public/ticker";
            string postData = "";
            string responseStr = (new MtGoxNetTools()).DoAuthenticatedAPIPost(url, apiKey, apiSecret, postData);
            logger.InfoFormat(url + " executed");
            return MtGoxMultiCurrencyTickerItem.getObjects(responseStr);
        }

        /// <summary>
        /// Multi Currency depth
        /// https://mtgox.com/api/1/BTCPLN/public/depth?raw
        /// https://mtgox.com/api/1/BTCAUD/public/depth?raw 
        /// </summary>
        /// <param name="currency1"></param>
        /// <param name="currency2"></param>
        /// <returns></returns>
        public MtGoxDepthInfo multiCurrencyDepth(MtGoxCurrencySymbol currency1, MtGoxCurrencySymbol currency2)
        {
            // TODO: See if the return type is actually the same as MtGoxDepthInfo or if we have to implement a new class
            string url = (this.baseURL) + "1/" + currency1.ToString() + currency2.ToString() + "depth?raw";
            string postData = "";
            string responseStr = (new MtGoxNetTools()).DoAuthenticatedAPIPost(url, apiKey, apiSecret, postData);
            logger.InfoFormat(url + " executed");
            return MtGoxDepthInfo.getObjects(responseStr);
        }

        /// <summary>
        /// Multi currency trades
        /// https://mtgox.com/api/1/BTCPLN/public/trades?raw
        /// https://mtgox.com/api/1/BTCAUD/public/trades?raw
        /// to get only the trades since a given trade id, you can add the parameter since=<trade_id>
        /// https://mtgox.com/api/1/BTCUSD/public/trades?since=0
        /// https://mtgox.com/api/1/BTCEUR/public/trades?since=1316312781670700
        /// For multi currency,also returns the primary value,"Y" or "N", the primary currency is always the buyers currency
        /// A trade can appear in more than one currency, to ignore duplicates, use only the trades having primary =Y
        /// example of returned data :
        /// {"date":1316312781,
        /// "price":"3.5599",
        /// "amount":"3.6900096",
        /// "price_int":"355990",
        /// "amount_int":"369000960",
        /// "tid":"1316312781670700",
        /// "price_currency":"EUR",
        /// "item":"BTC",
        /// "trade_type":"bid",
        /// "primary":"Y",
        /// "properties":"limit,mixed_currency"
        ///}
        /// </summary>
        /// <param name="currency1"></param>
        /// <param name="currency2"></param>
        /// <param name="since"></param>
        /// <returns></returns>
        public List<MtGoxMultiCurrencyTrade> multiCurrencyGetTrades(MtGoxCurrencySymbol currency1, MtGoxCurrencySymbol currency2, string since = "0", bool primaryOnly = false)
        {
            // TODO: Implement unit tests for this method
            string url = (this.baseURL) + "1/" + currency1.ToString() + currency2.ToString() + "depth?raw";
            string postData = "";
            string responseStr = (new MtGoxNetTools()).DoAuthenticatedAPIPost(url, apiKey, apiSecret, postData);
            logger.InfoFormat(url + " executed");
            return MtGoxMultiCurrencyTrade.getObjects(responseStr, primaryOnly);
        }
    }
}
